package org.szy.plugin.sys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.util.UpdateEntity;
import org.noear.solon.annotation.Inject;
import org.noear.solon.annotation.ProxyComponent;
import org.noear.solon.data.annotation.Tran;
import org.szy.core.common.enums.CommonStatusEnum;
import org.szy.core.common.exception.BaseException;
import org.szy.core.common.param.CommonMoveParam;
import org.szy.core.common.param.CommonStatusParam;
import org.szy.core.common.service.impl.BaseServiceImpl;
import org.szy.core.common.uilts.TreeBuildFactory;
import org.szy.plugin.sys.entity.SysMenu;
import org.szy.plugin.sys.mapper.SysMenuMapper;
import org.szy.plugin.sys.param.SysMenuQueryParam;
import org.szy.plugin.sys.pojo.SysMenuTree;
import org.szy.plugin.sys.service.SysMenuService;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static org.szy.plugin.sys.entity.table.SysMenuTableDef.SYS_MENU;

/**
 * 系统菜单Service接口实现类
 *
 * @author wangbuhao
 * @since 2023-06-25 10:36:16
 **/
@ProxyComponent
public class SysMenuServiceImpl extends BaseServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    @Inject
    private SysMenuMapper sysMenuMapper;

    @Override
    public QueryWrapper qwByQuery(SysMenuQueryParam param) {
        QueryWrapper qw = new QueryWrapper();
        if (StrUtil.isNotEmpty(param.getColumnField())) {
            qw.select(param.getColumnField().split(","));
        }
        if (StrUtil.isNotEmpty(param.getApplication())) qw.and(SYS_MENU.APPLICATION.eq(param.getApplication()));
        if (StrUtil.isNotEmpty(param.getCode())) {
            qw.and(SYS_MENU.CODE.eq(param.getCode()));
        }
        if (param.getType() != null) {
            qw.and(SYS_MENU.TYPE.eq(param.getType()));
        }
        if (param.getStatus() != null) {
            qw.and(SYS_MENU.STATUS.eq(param.getStatus()));
        }
        qw.orderBy(SYS_MENU.SORT.asc());
        return qw;
    }

    @Override
    public List<SysMenu> list(SysMenuQueryParam param) {
        QueryWrapper qw = qwByQuery(param);
        return list(qw);
    }

    @Override
    @Tran
    public boolean add(SysMenu entity) {
        boolean exists = exists(SYS_MENU.CODE.eq(entity.getCode()));
        if (exists) throw new BaseException("菜单标识已存在");
        entity.setPids(createNewPids(entity.getPid()));
        if (entity.getSort() == null) {
            long count = count();
            entity.setSort(Convert.toInt(count, 0) + 1);
        }
        return this.save(entity);
    }

    @Override
    public boolean edit(SysMenu entity) {
        boolean exists = exists(SYS_MENU.CODE.eq(entity.getCode()).and(SYS_MENU.ID.ne(entity.getId())));
        if (exists) throw new BaseException("菜单标识已存在");
        if (Objects.equals(entity.getId(), entity.getPid()))
            throw new BaseException("上级菜单不能选择自己");
        boolean existsApp = exists(SYS_MENU.APPLICATION.eq(entity.getApplication()).and(SYS_MENU.ID.eq(entity.getId())));
        entity.setPids(createNewPids(entity.getPid()));
        boolean update = updateById(entity);
        if (update && !existsApp) {
            // 更新应用分类
            SysMenu of = UpdateEntity.of(SysMenu.class);
            of.setApplication(entity.getApplication());
            sysMenuMapper.updateByQuery(of, QueryWrapper.create().and(SYS_MENU.PIDS.like(entity.getId())));
        }
        return update;
    }

    @Override
    public boolean deleteById(Long id) {
        return remove(SYS_MENU.ID.eq(id).or(SYS_MENU.PIDS.like(id)));
    }

    @Override
    public List<SysMenuTree> buildTrees(List<SysMenu> list) {
        List<SysMenuTree> lists = BeanUtil.copyToList(list, SysMenuTree.class);
        return new TreeBuildFactory<SysMenuTree>().doTreeBuild(lists);
    }

    @Override
    public boolean move(CommonMoveParam param) {
        SysMenu entity = this.getById(param.getId(), "id,pid,sort");
        QueryWrapper qw = new QueryWrapper().limit(1);
        qw.select("id,pid,sort").and(SYS_MENU.PID.eq(entity.getPid()));
        List<SysMenu> list;
        switch (param.getType()) {
            // 上移
            case "1":
                qw.and(SYS_MENU.SORT.lt(entity.getSort())).orderBy(SYS_MENU.SORT.desc());
                list = list(qw);
                if (list.size() == 0) throw new BaseException("没有可交换的上级菜单");
                break;
            // 下移
            case "2":
                qw.and(SYS_MENU.SORT.gt(entity.getSort())).orderBy(SYS_MENU.SORT.asc());
                list = list(qw);
                if (list.size() == 0) throw new BaseException("没有可交换的下级菜单");
                break;
            default:
                return false;
        }
        SysMenu moveEntity = list.get(0);

        SysMenu moveE = UpdateEntity.of(SysMenu.class, entity.getId());
        moveE.setSort(moveEntity.getSort());
        sysMenuMapper.update(moveE);

        SysMenu moveE2 = UpdateEntity.of(SysMenu.class, moveEntity.getId());
        moveE2.setSort(entity.getSort());
        sysMenuMapper.update(moveE2);

        return true;
    }

    @Override
    public boolean modifyStatus(CommonStatusParam param) {
        SysMenu entity = new SysMenu();
        entity.setStatus(param.getStatus());
        QueryWrapper qw = new QueryWrapper();
        qw.and(SYS_MENU.ID.eq(param.getId()).or(SYS_MENU.PIDS.like(param.getId())));
        return sysMenuMapper.updateByQuery(entity, qw) > 0;
    }

    @Override
    public List<String> listIdByPid(String pid) {
        QueryWrapper qw = new QueryWrapper();
        qw.select("id").and(SYS_MENU.PIDS.like(pid));
        return listAs(qw, String.class);
    }

    @Override
    public boolean createPerms(Long id) {
        SysMenu sysMenu = getById(id, "name", "pids", "permission", "code", "application");
        if (sysMenu == null) throw new BaseException("未找到菜单信息");
        if (StrUtil.isEmpty(sysMenu.getPermission())) throw new BaseException("该菜单没有权限标识，请补充权限标识");

        int count = Convert.toInt(count() + 1);
        String menuTitle = sysMenu.getName();
        String menuPerms = sysMenu.getPermission();
        String menuCode = sysMenu.getCode();
        String app = sysMenu.getApplication();
        String pids = sysMenu.getPids() + "," + id;

        String[] titles = {"_列表", "_详情", "_添加", "_更新", "_删除"};
        String[] permss = {"_list", "_detail", "_add", "_update", "_delete"};
        List<SysMenu> list = new ArrayList<>();
        for (int i = 0; i < titles.length; i++) {
            String title = titles[i];
            String perms = permss[i];
            SysMenu menu = new SysMenu();
            menu.setName(menuTitle + title);
            menu.setCode(menuCode + perms);
            menu.setPermission(menuPerms + perms);
            menu.setPid(id);
            menu.setPids(pids);
            menu.setSort(count + i);
            menu.setType(2);
            menu.setStatus(CommonStatusEnum.ENABLE.getKey());
            menu.setApplication(app);
            list.add(menu);
        }
        List<String> listPerms = list.stream().map(SysMenu::getPermission).collect(Collectors.toList());
        this.remove(SYS_MENU.PERMISSION.in(listPerms));
        return saveBatch(list);
    }
}
